package com.lxl.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lxl.chat.bean.Users;
import com.lxl.chat.bean.vo.FriendRequestVO;
import com.lxl.chat.bean.vo.MyFriendsVO;
import com.lxl.chat.entity.ChatMsgDO;
import com.lxl.chat.entity.FriendsRequestDO;
import com.lxl.chat.entity.MyFriendsDO;
import com.lxl.chat.entity.UsersDO;
import com.lxl.chat.idworker.Sid;
import com.lxl.chat.mapper.ChatMsgDOMapper;
import com.lxl.chat.mapper.FriendsRequestDOMapper;
import com.lxl.chat.mapper.MyFriendsDOMapper;
import com.lxl.chat.mapper.UsersDOMapper;
import com.lxl.chat.netty.ChatMsg;
import com.lxl.chat.netty.DataContent;
import com.lxl.chat.netty.UserChannelRel;
import com.lxl.chat.service.UserService;
import com.lxl.chat.util.FastDFSClient;
import com.lxl.chat.util.FileUtils;
import com.lxl.chat.util.JsonUtils;
import com.lxl.chat.util.QRCodeUtils;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UsersDOMapper userMapper;

    @Autowired
    private MyFriendsDOMapper myFriendsMapper;

    @Autowired
    private FriendsRequestDOMapper friendsRequestMapper;

    @Autowired
    private ChatMsgDOMapper chatMsgMapper;

    @Autowired
    private Sid sid;

    @Autowired
    private QRCodeUtils qrCodeUtils;

    @Autowired
    private FastDFSClient fastDFSClient;

    /**
     * 根据用户名查询是否存在这个用记
     *
     * @param username 用户名
     * @return 存在=true 不存在=false
     */
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    @Override
    public boolean queryUsernameIsExist(String username) {
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        Users result = userMapper.selectOne(wrapper);
        return result != null;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserForLogin(String username, String pwd) {
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        wrapper.eq("password", pwd);

        return userMapper.selectOne(wrapper);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Users saveUser(Users user) {

        String userId = sid.nextShort();

        // 为每个用户生成一个唯一的二维码
        String qrCodePath = "C://user" + userId + "qrcode.png";
        // muxin_qrcode:[username]
        qrCodeUtils.createQRCode(qrCodePath, "muxin_qrcode:" + user.getUsername());
        MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrCodePath);

        String qrCodeUrl = "";
        try {
            qrCodeUrl = fastDFSClient.uploadQRCode(qrCodeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        user.setQrcode(qrCodeUrl);

        user.setId(userId);
        userMapper.insert(user);

        return user;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Users updateUserInfo(Users user) {
        userMapper.updateById(user);
        return queryUserById(user.getId());
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    Users queryUserById(String userId) {
        UsersDO usersDO = userMapper.selectByPrimaryKey(userId);
        Users users = new Users();
        BeanUtils.copyProperties(usersDO, users);
        return users;
    }

    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    @Override
    public Integer preconditionSearchFriends(String myUserId, String friendUsername) {

        Users user = queryUserInfoByUsername(friendUsername);

        // 1. 搜索的用户如果不存在，返回[无此用户]
        if (user == null) {
            return com.imooc.enums.SearchFriendsStatusEnum.USER_NOT_EXIST.status;
        }

        // 2. 搜索账号是你自己，返回[不能添加自己]
        if (user.getId().equals(myUserId)) {
            return com.imooc.enums.SearchFriendsStatusEnum.NOT_YOURSELF.status;
        }

        // 3. 搜索的朋友已经是你的好友，返回[该用户已经是你的好友]

        QueryWrapper<MyFriendsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("my_user_id", myUserId);
        wrapper.eq("my_friend_user_id", user.getId());

        MyFriendsDO myFriendsDO = myFriendsMapper.selectOne(wrapper);
        if (myFriendsDO != null) {
            return com.imooc.enums.SearchFriendsStatusEnum.ALREADY_FRIENDS.status;
        }

        return com.imooc.enums.SearchFriendsStatusEnum.SUCCESS.status;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserInfoByUsername(String username) {
        QueryWrapper<Users> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        return userMapper.selectOne(wrapper);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public void sendFriendRequest(String myUserId, String friendUsername) {

        // 根据用户名把朋友信息查询出来
        Users friend = queryUserInfoByUsername(friendUsername);

        // 1. 查询发送好友请求记录表
        QueryWrapper<FriendsRequestDO> wrapper = new QueryWrapper<>();
        wrapper.eq("send_user_id", myUserId);
        wrapper.eq("accept_user_id", friend.getId());

        FriendsRequestDO friendRequest = friendsRequestMapper.selectOne(wrapper);
        if (friendRequest == null) {
            // 2. 如果不是你的好友，并且好友记录没有添加，则新增好友请求记录
            String requestId = sid.nextShort();

            FriendsRequestDO request = new FriendsRequestDO();
            request.setId(requestId);
            request.setSendUserId(myUserId);
            request.setAcceptUserId(friend.getId());
            request.setRequestDateTime(new Date());
            friendsRequestMapper.insert(request);
        }
    }

    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    @Override
    public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) {
        return userMapper.queryFriendRequestList(acceptUserId);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public void deleteFriendRequest(String sendUserId, String acceptUserId) {
        QueryWrapper<FriendsRequestDO> wrapper = new QueryWrapper<>();
        wrapper.eq("send_user_id", sendUserId);
        wrapper.eq("accept_user_id", acceptUserId);
        friendsRequestMapper.delete(wrapper);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public void passFriendRequest(String sendUserId, String acceptUserId) {
        saveFriends(sendUserId, acceptUserId);
        saveFriends(acceptUserId, sendUserId);
        deleteFriendRequest(sendUserId, acceptUserId);

        Channel sendChannel = UserChannelRel.get(sendUserId);
        if (sendChannel != null) {
            // 使用websocket主动推送消息到请求发起者，更新他的通讯录列表为最新
            DataContent dataContent = new DataContent();
            dataContent.setAction(com.imooc.enums.MsgActionEnum.PULL_FRIEND.type);

            sendChannel.writeAndFlush(
                    new TextWebSocketFrame(
                            JsonUtils.objectToJson(dataContent)));
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    void saveFriends(String sendUserId, String acceptUserId) {
        MyFriendsDO myFriends = new MyFriendsDO();
        String recordId = sid.nextShort();
        myFriends.setId(recordId);
        myFriends.setMyFriendUserId(acceptUserId);
        myFriends.setMyUserId(sendUserId);
        myFriendsMapper.insert(myFriends);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<MyFriendsVO> queryMyFriends(String userId) {
        return userMapper.queryMyFriends(userId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public String saveMsg(ChatMsg chatMsg) {

        com.lxl.chat.bean.ChatMsg msgDB = new com.lxl.chat.bean.ChatMsg();
        String msgId = sid.nextShort();
        msgDB.setId(msgId);
        msgDB.setAcceptUserId(chatMsg.getReceiverId());
        msgDB.setSendUserId(chatMsg.getSenderId());
        msgDB.setCreateTime(new Date());
        msgDB.setSignFlag(com.imooc.enums.MsgSignFlagEnum.unsign.type);
        msgDB.setMsg(chatMsg.getMsg());

        ChatMsgDO chatMsgDO = new ChatMsgDO();
        BeanUtils.copyProperties(msgDB, chatMsgDO);

        chatMsgMapper.insertSelective(chatMsgDO);

        return msgId;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateMsgSigned(List<String> msgIdList) {
        chatMsgMapper.batchUpdateMsgSigned(msgIdList);
    }

    // @Transactional(propagation = Propagation.SUPPORTS)
    // @Override
    // public List<ChatMsg> getUnReadMsgList(String acceptUserId) {
    //
    //     Example chatExample = new Example(ChatMsg.class);
    //     Example.Criteria chatCriteria = chatExample.createCriteria();
    //     chatCriteria.andEqualTo("signFlag", 0);
    //     chatCriteria.andEqualTo("acceptUserId", acceptUserId);
    //
    //     List<ChatMsg> result = chatMsgMapper.selectByExample(chatExample);
    //
    //     return result;
    // }
}
